#include "cx_pwm.h"

void STM32F4xx_PWM_Handler(struct pwm_handler *pwm,cx_uint32_t HandleAttr, void * value)
{
    cx_uint32_t tmp;
#define CCRx(x) (pwm->htim->CCR##x)
#define ARR (pwm->htim->ARR)
#define ptoUINT32(x) (*((cx_uint32_t *)x))
#define TIM_INTR_ENABLE_REG (pwm->htim->DIER)
#define PWM_INTR_ENABLE_BIT(x) (2 << x)
#define PWM_CTRL_ENABLE_REG (pwm->htim->CCER)
#define PWM_CTRL_ENABLE_BIT(x) (1 << ((x) * 4))
    switch(HandleAttr)
    {
        case CX_PWM_HANDLER_SET_PULSE:
            switch (pwm->channel)
            {
                case 0:
                    CCRx(1) = ptoUINT32(value);
                break;
                case 1:
                    CCRx(2) = ptoUINT32(value);
                break;
                case 2:
                    CCRx(3) = ptoUINT32(value);
                break;
                case 3:
                    CCRx(4) = ptoUINT32(value);
                break;
                default:
                break;
            }
        break;
        case CX_PWM_HANDLER_SET_FREQ:
            ARR=pwm->FreqK / (*((cx_uint32_t *)value));
        break;
        case CX_PWM_HANDLER_CTRL_START:
            PWM_CTRL_ENABLE_REG |= PWM_CTRL_ENABLE_BIT((pwm->channel));
        break;
        case CX_PWM_HANDLER_CTRL_STOP:
						PWM_CTRL_ENABLE_REG &= ~PWM_CTRL_ENABLE_BIT((pwm->channel));
        break;
        case CX_PWM_HANDLER_GET_FREQ:
        break;
        case CX_PWM_HANDLER_GET_PULSE:
        break;
        case CX_PWM_HANDLER_GET_STATUS:
        break;
        default:
        break;
    }
    if((HandleAttr & CX_PWM_HANDLER_CFG_ENABLE_INTR) == CX_PWM_HANDLER_CFG_ENABLE_INTR)
    {
        HandleAttr &= ~CX_PWM_HANDLER_CFG_ENABLE_INTR;
        switch(HandleAttr)
        {
            case CX_PWM_HANDLER_INTR_PULSE_FINISH:
                TIM_INTR_ENABLE_REG |= PWM_INTR_ENABLE_BIT((pwm->channel));
            break;
            default:
            break;
        }
    }
    if((HandleAttr & CX_PWM_HANDLER_CFG_DISABLE_INTR) == CX_PWM_HANDLER_CFG_DISABLE_INTR)
    {
        HandleAttr &= ~CX_PWM_HANDLER_CFG_DISABLE_INTR;
        switch(HandleAttr)
        {
            case CX_PWM_HANDLER_INTR_PULSE_FINISH:
                TIM_INTR_ENABLE_REG &= ~PWM_INTR_ENABLE_BIT((pwm->channel));
            break;
            default:
            break;
        }
    }
}

void STM32F4xx_PWM_IRQHandler(struct pwm_handler *self,cx_uint32_t CX_PWM_HANDLER_INTR,void *args)
{
    if((CX_PWM_HANDLER_INTR & CX_HANDLER_CLASS_MASK) != CX_HANDLER_CLASS_INTR)
        return;
    if((CX_PWM_HANDLER_INTR & CX_PWM_HANDLER_INTR_PULSE_FINISH) != 0)
    {
        //
    }
}

int CX_PWM_ON_OFF(pwm_handler_t *pwm, cx_uint32_t CX_PWM_ON_OFF)
{
    if(CX_PWM_ON_OFF != 0)
        pwm->cbHandler(pwm, CX_PWM_HANDLER_CTRL_START, CX_NULL);
    else
        pwm->cbHandler(pwm, CX_PWM_HANDLER_CTRL_STOP, CX_NULL);
    return 0;
}
int CX_PWM_SetPulse(pwm_handler_t *pwm, cx_uint32_t pulse)
{
    pwm->cbHandler(pwm, CX_PWM_HANDLER_SET_PULSE, &pulse);
    return 0;
}
int CX_PWM_SetFrequency(pwm_handler_t *pwm, cx_uint32_t frequency_Hz)
{
    pwm->cbHandler(pwm, CX_PWM_HANDLER_SET_FREQ, &frequency_Hz);
    return 0;
}
int CX_PWM_CfgIntr(pwm_handler_t *pwm, cx_uint32_t CX_PWM_HANDLER_CFG_INTR)
{
    pwm->cbHandler(pwm, CX_PWM_HANDLER_CFG_INTR, CX_NULL);
		return 0;
}

void CX_PWM_IRQHandler(pwm_handler_t *pwm,cx_uint32_t CX_PWM_HANDLER_INTR,void *args)
{
    pwm->cbIRQHandler(pwm, CX_HANDLER_CLASS_INTR | CX_PWM_HANDLER_INTR, args);   
}

pwm_handler_t TIM2_Channel_1_GPIOA5 = 
{
    .cbHandler = STM32F4xx_PWM_Handler,
    .channel = 0,
    .flags = 0,
    .freq = 0,
    .FreqK = 84000000 / 20,
    .htim = TIM2,
    .pulse = 0
};
